﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows.Forms;

namespace ReBasic.Helper
{
    public class MsraFormatHelper
    {
        StreamReader sr;
        StreamWriter sws, swc;
        FileStream fsr, fsws, fswc;

        public event MainFrame.TripleHandler ProcessEvent;
        public event MainFrame.InfoHandler StateEvent;
        
        int dfs_tree(TreeNode tr, ref List<string> result)
        {
            int state = 0;
            if (tr.Nodes.Count == 0)        //Leaf
            {
                tr.Tag = new StringBuilder(tr.Text);
                return 0;
            }
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < tr.Nodes.Count; i++)
            { 
                int x = dfs_tree(tr.Nodes[i], ref result);
                if (!(tr.Text == "NP" && i == 0 &&
                    (tr.Nodes[i].Text == "DT" || tr.Nodes[i].Text == "PRP$")))
                { 
                    if (sb.Length != 0)
                        sb.Append(' ');
                    sb.Append(tr.Nodes[i].Tag as StringBuilder);
                }
                if (x == 1 || x == -1)
                    state = -1;
            }
            tr.Tag = sb;
            if (state == 0 && tr.Text == "NP")
            { 
                state = 1;
                result.Add(sb.ToString());
            }
            return state;
        }

        public List<string> find_base_np(TreeNode tr)
        { 
            List<string> res = new List<string>();
            int state = dfs_tree(tr, ref res);
            if (state == 0 && tr.Text == "NP")
                res.Add((tr.Tag as StringBuilder).ToString());
            for (int i = 0; i < res.Count; i++)
                if (res[i] == "")
                { 
                    res.RemoveAt(i);
                    i--;
                }
            res = res.Distinct().ToList();
            return res;
        }

        public void get_sentence(TreeNode tr, ref StringBuilder sb)
        {
            if (tr.Nodes.Count == 0)
            { 
                if (sb.Length != 0)
                    sb.Append(' ');
                sb.Append(tr.Text);
                return;
            }
            foreach (TreeNode chd in tr.Nodes)
                get_sentence(chd, ref sb);
        }

        public TreeNode generate_parse_tree(String parse_result, ref int pos)
        {
            bool leaf_node;
            TreeNode res = new TreeNode();
            StringBuilder sb = new StringBuilder();
            if (parse_result[pos] == '(')
            {
                leaf_node = false;
                pos++;
            }
            else leaf_node = true;
            while (parse_result[pos] != ' ' && parse_result[pos] != ')')
                sb.Append(parse_result[pos++]);
            res.Text = sb.ToString();
            if (!leaf_node)
                pos++;
            while (parse_result[pos] != ')')
            { 
                TreeNode tr = generate_parse_tree(parse_result, ref pos);
                res.Nodes.Add(tr);
                if (parse_result[pos] == ' ')
                    pos++;
            }
            if (!leaf_node)
                pos++;
            return res;
        }

        public void deal_with_single(String parse_result, StreamWriter sws, StreamWriter swc)
        { 
            int pos = 0;
            TreeNode tr = generate_parse_tree(parse_result, ref pos);
            #region Sentence
            StringBuilder sb = new StringBuilder();
            get_sentence(tr, ref sb);
            sws.WriteLine(sb.ToString().ToLower());
            #endregion
            #region Chunking
            List<string> lst = find_base_np(tr);
            for (int i = 0; i < lst.Count; i++)
            {
                if (i > 0)
                    swc.Write('\t');
                swc.Write(lst[i].ToLower());
            }
            swc.WriteLine();
            #endregion
        }

        public void Work()
        { 
            int cnt = 0;
            fsr = new FileStream(MainFrame.MsraPath, FileMode.Open);
            sr = new StreamReader(fsr, Encoding.UTF8);
            fsws = new FileStream(MainFrame.SentPath, FileMode.Create);
            sws = new StreamWriter(fsws, Encoding.UTF8);
            fswc = new FileStream(MainFrame.ChunkPath, FileMode.Create);
            swc = new StreamWriter(fswc, Encoding.UTF8);
            StreamWriter log = new StreamWriter(MainFrame.DataPath + "log.txt", true);
            while (!sr.EndOfStream)
            { 
                string rd_str = sr.ReadLine();
                if (rd_str == "")   continue;
                string[] spt = rd_str.Split('\t');
                deal_with_single(spt[2], sws, swc);
                if (++cnt % 10000 == 0)
                    ProcessEvent(cnt, cnt, 0);
            }
            StateEvent("Gen mrsa info complete, with " + cnt + " sentences.", true);
            log.WriteLine(cnt);
            log.Close();
            sr.Close();     fsr.Close();
            swc.Close();    fswc.Close();
            sws.Close();    fsws.Close();
        }

    }
}
